package stamboom;

import java.util.*;

public class Persoon implements java.io.Serializable{

    // ********datavelden**************************************
    private int persNr;
    private String[] voornamen;
    private String achternaam;
    private String tussenvoegsel;
    private GregorianCalendar gebdat;
    private Gezin ouders;
    private ArrayList<Gezin> gezinnen;
    private Geslacht geslacht;  
  

   // ********constructoren***********************************
    /**
     * er wordt een persoon gecreeerd met persoonsnummer persNr en met als
     * voornamen vnamen, achternaam anaam, tussenvoegsel tvoegsel, geboortedatum
     * gebdat, gelsacht geslacht en een gegeven ouderlijk gezin (mag null
     * (=onbekend) zijn); de creatie van deze persoon is voortaan ook bij het
     * ouderlijk gezin bekend, mits dit bekend is; NB. de eerste letter van een
     * voornaam en achternaam wordt naar een hoofdletter omgezet, alle andere
     * letters zijn kleine letters
     *
     */
    public Persoon(int persNr, String[] vnamen, String anaam, String tvoegsel,
            GregorianCalendar gebdat, Geslacht geslacht, Gezin ouderlijkGezin) 
    {
        this.persNr = persNr;
        voornamen = vnamen;
        tussenvoegsel = tvoegsel;
        this.gebdat = gebdat;
        this.geslacht = geslacht;
        this.ouders = ouderlijkGezin;
       
        
        achternaam = capitalizeString(anaam);
        int i = 0;
        for(String str : vnamen){
            voornamen[i] = capitalizeString(str);
            i++;
        }
        this.gezinnen = new ArrayList<Gezin>();
        //this.ouders = ouderlijkGezin;
        setOuders(ouderlijkGezin);     
    }

    public static String capitalizeString(String string) {
        char[] chars = string.toLowerCase().toCharArray();
        boolean found = false;
        for (int i=0; i<chars.length; i++){
            if(!found && Character.isLetter(chars[i])){
                chars[i] = Character.toUpperCase(chars[i]);
                found = true;
            } else if (Character.isWhitespace(chars[i]) || chars[i]=='.' || chars[i]== '\'' ){
                found=false;
            } 
        }
        return String.valueOf(chars);
    }
    // ********methoden****************************************
    /**
     * @return de achternaam van deze persoon
     */
    public String getAchternaam() {
        return achternaam;
    }

    /**
     * @return de geboortedatum van deze persoon in de stringvorm
     *         dagnummer-maandnummer-jaartal
     */
    public String getGebdat() {
        return gebdat.get(Calendar.DAY_OF_MONTH) + "-" +
                (gebdat.get(Calendar.MONTH)+1) + "-" + gebdat.get(Calendar.YEAR);
    }

    /**
     *
     * @return het geslacht van deze persoon
     */
    public Geslacht getGeslacht(){
        return geslacht;
    };

    /**
     *
     * @return de voorletters van de voornamen; elke voorletter wordt gevolgd door
     *         een punt
     */
    public String getInitialen() {
        
        String namen = "";
        for(String str : voornamen){
            namen += str.charAt(0)+". ";
        }
        return namen;
    }

    /**
     *
     * @return de initialen gevolgd door een eventueel tussenvoegsel en afgesloten
     *         door de achternaam
     */
    public String getNaam() {
        //todo
        String naam = "";
        naam += getInitialen()+" ";
        if (tussenvoegsel != null && !tussenvoegsel.equals("")){
            naam += tussenvoegsel + " ";
        }
        naam += achternaam;
        return naam;
    }

    /**
     * @return het nummer van deze persoon
     */
    public int getNr() {
        return persNr;
    }

   /**
     * @return een iterator over de gezinnen waar deze persoon bij betrokken is
     */
    public Iterator<Gezin> getGezinnen() {
        return gezinnen.iterator();
    }

     /**
     * @return het tussenvoegsel van de naam van deze persoon (kan een lege string
     *         zijn)
     */
    public String getTussenvoegsel() {
        return tussenvoegsel;
    }

    /**
     * @return alle voornamen onderling gescheiden door een spatie
     */
    public String getVoornamen() {
        StringBuilder init = new StringBuilder();
        for (String s : voornamen) {
            init.append(s + " ");
        }
        // de laatste spatie verwijderen:
        if (init.length() > 0) {
            init.deleteCharAt(init.length() - 1);
        }
        return init.toString();
    }

    /**
     * @return de standaard gegevens van deze mens (naam, geslacht en
     *         geboortedatum)
     */
    public String standaardGegevens() {
        return getNaam() + " (" + getGeslacht() + ") " + getGebdat();
    }

     /**
     * @return het ouderlijk gezin van deze persoon, indien bekend, anders null
     */
    public Gezin getOuders() {
        return ouders;
    }
    
        
     /**
     * Als het ouderlijk gezin ('ouders') van deze persoon (this) nog onbekend is krijgt deze
     * het gegeven ouderlijk gezin toegewezen en tevens wordt deze persoon (this)
     * als kind in dat gegeven ouderlijk gezin geregistreerd.
     * Als de ouders bij aanroep al bekend zijn, verandert er niets.
     */
    public void setOuders(Gezin ouders) {
        //todo
        if (this.ouders == null && ouders !=null){
            this.ouders = ouders;
            ouders.breidUitMet(this);
        }
            
    }

     /**
     * @return voornamen, eventueel tussenvoegsel en achternaam, geslacht,
     *         geboortedatum, namen van de ouders, mits bekend, en nummers van de
     *         gezinnen waarbij deze persoon betrokken is (geweest)
     */
    @Override
    public String toString() {
        StringBuilder s = new StringBuilder();

        s.append(standaardGegevens());

        if (ouders != null) {
            s.append("; 1e ouder: " + ouders.getOuder1().getNaam());
            s.append("; 2e ouder: " + ouders.getOuder2().getNaam());
        }
        if (!gezinnen.isEmpty()) {
            s.append("; is ouder in gezin ");

            for (Gezin g : gezinnen) {
                s.append(g.getNr() + " ");
            }
        }

        return s.toString();
    }
 /**
     * als g nog niet bij deze persoon staat geregistreerd wordt g bij deze
     * persoon geregistreerd en anders verandert er niets
     *
     * @param g
     *          een nieuw gezin waarin deze persoon een ouder is
     *
     */
    void wordtOuderIn(Gezin g) {
        if (!gezinnen.contains(g)) {
            gezinnen.add(g);
        }
    }
    

      /**
     *
     * @return It works!
     */
    public ArrayList<PersoonUitGeneratie> getStamboom(){
        ArrayList<PersoonUitGeneratie> lijst = new ArrayList<PersoonUitGeneratie>();
        lijst.add(new PersoonUitGeneratie(standaardGegevens(), 0));
        if (ouders != null)
        {
            lijst.addAll(ouders.stamboomgegevens(1));
        }
        return lijst;
    }
    
     /**
     * Voegt de stamboomgegevens van deze persoon toe aan een lijst
     *
     * @param generatie de generatie van deze persoon in de lijst
     * @param lijst (niet null)
     */
    public void voegStamboomgegevensToeAan(ArrayList<PersoonUitGeneratie> lijst, int generatie) {
        generatie++;

        try {
            Persoon o1 = ouders.getOuder1();
            lijst.add(new PersoonUitGeneratie(o1.getNaam() + " (" + o1.getGeslacht() + ") " + o1.getGebdat(), generatie));
        } catch (NullPointerException ex) {
        }



        try {
            ouders.getOuder1().voegStamboomgegevensToeAan(lijst, generatie);
        } catch (NullPointerException ex) {
        }

        try {
            Persoon o2 = ouders.getOuder2();
            lijst.add(new PersoonUitGeneratie(o2.getNaam() + " (" + o2.getGeslacht() + ") " + o2.getGebdat(), generatie));

        } catch (NullPointerException ex) {
        }

        try {
            ouders.getOuder2().voegStamboomgegevensToeAan(lijst, generatie);
        } catch (NullPointerException ex) {
        }

    }

    
     /**
     * @return de stamboomgegevens van deze persoon in de vorm van een String,
     * waarbij iedere persoon op een aparte regel staat en iedere * voorgaande
     * generatie twee posities inspringt.
     */
    public String stamboomGegevensAlsString() {
        
        ArrayList<PersoonUitGeneratie> arr = new ArrayList<>();
        arr.add(new PersoonUitGeneratie(getNaam(), 0));
        voegStamboomgegevensToeAan(arr, 0);
        String returnW = "";
        for (PersoonUitGeneratie p : arr) {
            for (int i = 0; i < p.getGeneratie(); i++) {
                returnW += "  ";
            }
            returnW += p.getTekst() + "\n";
        }
        return returnW;
    }

    
}
